package com.entmanage.base.oa.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.entmanage.base.hrm.domain.HrmEmployee;
import com.entmanage.base.hrm.service.IHrmEmployeeService;
import com.entmanage.common.core.domain.entity.SysUser;
import com.entmanage.common.utils.DateUtils;
import com.entmanage.common.utils.StringUtils;
import com.entmanage.system.service.ISysUserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.entmanage.common.utils.SecurityUtils;
import com.entmanage.base.oa.mapper.OaLeaveApplyMapper;
import com.entmanage.base.oa.domain.OaLeaveApply;
import com.entmanage.base.oa.service.IOaLeaveApplyService;

/**
 * 请假申请Service业务层处理
 *
 * @author lsq
 * @date 2025-09-10
 */
@Service
public class OaLeaveApplyServiceImpl implements IOaLeaveApplyService
{
    @Autowired
    private OaLeaveApplyMapper oaLeaveApplyMapper;

    @Autowired
    private JavaMailSender javaMailSender;

    @Autowired
    private ISysUserService sysUserService;

    private static final Logger log = LoggerFactory.getLogger(OaLeaveApplyServiceImpl.class);

    /**
     * 查询请假申请
     *
     * @param applyId 请假申请主键
     * @return 请假申请
     */
    @Override
    public OaLeaveApply selectOaLeaveApplyByApplyId(Long applyId)
    {
        return oaLeaveApplyMapper.selectOaLeaveApplyByApplyId(applyId);
    }

    /**
     * 查询请假申请列表
     *
     * @param oaLeaveApply 请假申请
     * @return 请假申请
     */
    @Override
    public List<OaLeaveApply> selectOaLeaveApplyList(OaLeaveApply oaLeaveApply)
    {
        return oaLeaveApplyMapper.selectOaLeaveApplyList(oaLeaveApply);
    }

    /**
     * 新增请假申请
     *
     * @param oaLeaveApply 请假申请
     * @return 结果
     */
    @Override
    public int insertOaLeaveApply(OaLeaveApply oaLeaveApply)
    {
        // 保存用户和部门id
        oaLeaveApply.setUserId(SecurityUtils.getUserId());
        oaLeaveApply.setDeptId(SecurityUtils.getDeptId());
    oaLeaveApply.setCreateBy(SecurityUtils.getUsername());
        oaLeaveApply.setCreateTime(DateUtils.getNowDate());
        return oaLeaveApplyMapper.insertOaLeaveApply(oaLeaveApply);
    }

    /**
     * 修改请假申请
     *
     * @param oaLeaveApply 请假申请
     * @return 结果
     */
    @Override
    public int updateOaLeaveApply(OaLeaveApply oaLeaveApply)
    {
        oaLeaveApply.setUpdateTime(DateUtils.getNowDate());
    oaLeaveApply.setUpdateBy(SecurityUtils.getUsername());
        return oaLeaveApplyMapper.updateOaLeaveApply(oaLeaveApply);
    }

    /**
     * 批量删除请假申请
     *
     * @param applyIds 需要删除的请假申请主键
     * @return 结果
     */
    @Override
    public int deleteOaLeaveApplyByApplyIds(Long[] applyIds)
    {
        return oaLeaveApplyMapper.deleteOaLeaveApplyByApplyIds(applyIds);
    }

    /**
     * 删除请假申请信息
     *
     * @param applyId 请假申请主键
     * @return 结果
     */
    @Override
    public int deleteOaLeaveApplyByApplyId(Long applyId)
    {
        return oaLeaveApplyMapper.deleteOaLeaveApplyByApplyId(applyId);
    }

    @Override
    @Async
    public void sendLeaveApprovalEmail(
            List<Long> approverIds,
            List<Long> ccIds,
            String leaveType,
            String startTime,
            String endTime,
            String applicantName) {

        log.info("【开始发送请假审批邮件】类型={}，审核人IDs={}, 抄送IDs={}",
                leaveType,
                approverIds != null ? approverIds : "无",
                ccIds != null ? ccIds : "无");

        // 参数基本校验
        if (StringUtils.isEmpty(leaveType)) {
            log.warn("邮件发送中止：请假类型为空");
            return;
        }
        if (StringUtils.isEmpty(startTime) || StringUtils.isEmpty(endTime)) {
            log.warn("邮件发送中止：时间范围缺失");
            return;
        }

        Set<String> toEmails = new HashSet<>();
        Set<String> ccEmails = new HashSet<>();

        // ✅ 使用 SysUserService 从 sys_user 表查询邮箱
        if (approverIds != null && !approverIds.isEmpty()) {
            List<SysUser> approvers = sysUserService.selectUserByIds(approverIds);
            toEmails.addAll(filterValidEmails(approvers, "审核人"));
        }

        if (ccIds != null && !ccIds.isEmpty()) {
            List<SysUser> ccs = sysUserService.selectUserByIds(ccIds);
            ccEmails.addAll(filterValidEmails(ccs, "抄送人"));
        }

        if (toEmails.isEmpty() && ccEmails.isEmpty()) {
            log.warn("未找到任何有效邮箱地址，终止发送");
            return;
        }

        // 构建邮件内容
        String subject = "[请假申请] " + applicantName + " 申请" + leaveType + " - " ;
        String content = String.format(
                "您好：\n\n" +
                        "%s 提交了一条【%s】请假申请，请假时间为：%s 至 %s。\n\n" +
                        "请登录OA系统进行查看或审批。\n\n" +
                        "—— OA系统自动通知",
                applicantName != null ? applicantName : "某员工",
                leaveType, startTime, endTime
        );

        try {
            SimpleMailMessage message = new SimpleMailMessage();
            // 修改为你的实际发件邮箱
            message.setFrom("1911708828@qq.com");
            message.setSubject(subject);
            message.setText(content);

            // 设置收件人（To）和抄送人（Cc）
            if (!toEmails.isEmpty()) {
                message.setTo(toEmails.toArray(new String[0]));
                javaMailSender.send(message);
                toEmails.forEach(email -> log.info("邮件已发送至审核人: {}", email));
            }

            if (!ccEmails.isEmpty()) {
                // 注意：JavaMail 不支持 To + Cc 同时发送的 SimpleMailMessage 批量构造
                // 我们这里为 Cc 单独再发一次（或者你可以用 MimeMessage）
                SimpleMailMessage ccMessage = new SimpleMailMessage(message);
                ccMessage.setTo(ccEmails.toArray(new String[0]));
                javaMailSender.send(ccMessage);
                ccEmails.forEach(email -> log.info("邮件已抄送至: {}", email));
            }

            log.info("【邮件发送完成】共发送 {} 封邮件", toEmails.size() + ccEmails.size());

        } catch (Exception e) {
            log.error("发送邮件时发生异常", e);
        }
    }

    /**
     * 从 SysUser 列表中提取非空邮箱
     */
    private Set<String> filterValidEmails(List<SysUser> users, String role) {
        return users.stream()
                .filter(user -> user != null && StringUtils.isNotEmpty(user.getEmail()))
                .map(SysUser::getEmail)
                .collect(Collectors.toSet());
    }

    @Override
    public List<OaLeaveApply> selectByApproverId(Long approverId) {
        return oaLeaveApplyMapper.selectByApproverId(approverId);
    }

    @Override
    public List<OaLeaveApply> selectByCcId(Long currentUserId) {
        return oaLeaveApplyMapper.selectByCcId(currentUserId);
    }

}
